home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / plnk081.zip / pilot-link.0.8.1 / libsock / dlp.c < prev    next >
C/C++ Source or Header  |  1997-08-03  |  56KB  |  2,328 lines

  1. /* dlp.c:  Pilot DLP protocol
  2.  *
  3.  * Copyright (c) 1996, 1997, Kenneth Albanowski
  4.  *
  5.  * This is free software, licensed under the GNU Public License V2.
  6.  * See the file COPYING for details.
  7.  */
  8.  
  9. /*@+matchanyintegral@*/
  10. /*@-predboolint@*/
  11. /*@-boolops@*/ 
  12.  
  13. #include <stdio.h>
  14. #include "pi-source.h"
  15. #include "pi-socket.h"
  16. #include "pi-dlp.h"
  17. #include "pi-syspkt.h"
  18.  
  19. #define get_date(ptr) (dlp_ptohdate((ptr)))                        
  20.  
  21. #define set_date(ptr,val) (dlp_htopdate((val),(ptr)))
  22.  
  23. #define DLP_BUF_SIZE 0xffff
  24. static /*@checked@*/ unsigned char dlp_buf[DLP_BUF_SIZE];
  25. static /*@checked@*/ unsigned char exec_buf[DLP_BUF_SIZE];
  26.  
  27. char * dlp_errorlist[] = { 
  28.   "No error",
  29.   "General System error",
  30.   "Illegal Function",
  31.   "Out of memory",
  32.   "Invalid parameter",
  33.   "Not found",
  34.   "None Open",
  35.   "Already Open",
  36.   "Too many Open",
  37.   "Already Exists",
  38.   "Cannot Open",
  39.   "Record deleted",
  40.   "Record busy",
  41.   "Operation not supported",
  42.   "-Unused-",
  43.   "Read only",
  44.   "Not enough space",
  45.   "Limit exceeded",
  46.   "Sync cancelled",
  47.   "Bad arg wrapper",
  48.   "Argument missing",
  49.   "Bad argument size"
  50. };
  51.  
  52. char * dlp_strerror(int error) {
  53.   if (error<0)
  54.     error = -error;
  55.   if ((unsigned int)error>sizeof(dlp_errorlist))
  56.     return "Unknown error";
  57.   else
  58.     return dlp_errorlist[error];
  59. }
  60.  
  61. int dlp_trace = 0;
  62.  
  63. #ifndef NO_DLP_TRACE
  64. #define DLP_TRACE
  65.  
  66. #define Trace(name) \
  67.   if (dlp_trace)    \
  68.     fprintf(stderr, "DLP %d: %s\n", sd, #name);
  69. #define Expect(count)    \
  70.   if (result < count) {  \
  71.     if (result < 0) {    \
  72.       if (dlp_trace)     \
  73.         fprintf(stderr, "Result: Error: %s (%d)\n", dlp_errorlist[-result], result); \
  74.     } else {             \
  75.       if (dlp_trace)     \
  76.         fprintf(stderr, "Result: Read %d bytes, expected at least %d\n", result, count); \
  77.       result = -128;     \
  78.     }                    \
  79.     return result;       \
  80.   } else                 \
  81.     if (dlp_trace)       \
  82.       fprintf(stderr, "Result: No error, %d bytes\n", result);
  83.   
  84. #else
  85.  
  86. #define Trace(name)
  87. #define Expect(count)   \
  88.   if (result < count) { \
  89.     if (result >= 0)    \
  90.       result = -128;    \
  91.     return result;      \
  92.   }
  93.   
  94. #endif
  95.  
  96.  
  97. #if 0
  98. /* Eventual code to dynamically allocate buffer */
  99. void * dlp_buffer(int sd, int cmd, int arg, int arglen, struct pi_socket * ps)
  100. {
  101.   unsigned char * buf;
  102.   *ps = pi_find_socket(sd);
  103.   if (*ps)
  104.     return 0;
  105.   
  106.   len = 50 + msglen;
  107.   if (ps->dlpbuflen < len) {
  108.     ps->dlpbuflen = len+1024;
  109.     if (ps->dlpbuf) 
  110.       ps->dlpbuf = realloc(ps->dlpbuf, ps->dlpbuflen);
  111.     else
  112.       ps->dlpbuf = malloc(ps->dlpbuflen);
  113.   }
  114.   
  115.   buf = ps->dlpbuf;
  116.   
  117.   buf[0] = (unsigned char)cmd;
  118.   buf[1] = etc.
  119.   
  120. }
  121. #endif
  122.  
  123. int dlp_exec(int sd, int cmd, int arg, 
  124.              const unsigned char /*@null@*/ *msg, int msglen, 
  125.              unsigned char /*@out@*/ /*@null@*/ *result, int maxlen)
  126.  /*@modifies *result, exec_buf;@*/
  127.  /*@-predboolint -boolops@*/
  128. {
  129.   int i;
  130.   int err;
  131.   
  132.   exec_buf[0] = (unsigned char)cmd;
  133.   if (msg && arg && msglen) {
  134.     memcpy(&exec_buf[6], msg, msglen);
  135.     exec_buf[1] = (unsigned char)1;
  136.     exec_buf[2] = (unsigned char)(arg | 0x80);
  137.     exec_buf[3] = (unsigned char)0;
  138.     set_short(exec_buf+4, msglen);
  139.     i = msglen+6;
  140.   } else {
  141.     exec_buf[1] = (unsigned char)0;
  142.     i = 2;
  143.   }
  144.  
  145.   if (pi_write(sd, &exec_buf[0], i)<i) {
  146.     errno = -EIO;
  147.     return -1;
  148.   }
  149.  
  150.   i = pi_read(sd, &exec_buf[0], DLP_BUF_SIZE);
  151.  
  152.   err = get_short(exec_buf+2);
  153.   
  154.   if (err != 0) {
  155.     errno = -EIO;
  156.     return -err;
  157.   }
  158.  
  159.   if (exec_buf[0] != (unsigned char)(cmd | 0x80)) { /* received wrong response */
  160.     errno = -ENOMSG;
  161.     return -1;
  162.   }
  163.   
  164.   if ((exec_buf[1] == (unsigned char)0) || (result==0)) /* no return blocks or buffers */
  165.     return 0; 
  166.     
  167.   /* assume only one return block */
  168.   if ((exec_buf[4] & 0xC0) == 0xC0) { /* Long arg */
  169.       i = get_long(exec_buf+6);
  170.       
  171.       if (i>maxlen)
  172.         i = maxlen;
  173.         
  174.       memcpy(result, &exec_buf[10], i);
  175.   } else if (exec_buf[4] & 0x80) { /* Short arg */
  176.       i = get_short(exec_buf+6);
  177.       
  178.       if (i>maxlen)
  179.         i = maxlen;
  180.         
  181.       memcpy(result, &exec_buf[8], i);
  182.   } else { /* Tiny arg */
  183.       i = (int)exec_buf[5];
  184.  
  185.       if (i>maxlen)
  186.         i = maxlen;
  187.         
  188.       memcpy(result, &exec_buf[6], i);
  189.   }
  190.  
  191.   return i;
  192.   
  193. }
  194.  
  195. /* These conversion functions are strictly for use within the DLP layer.
  196.    This particular date/time format does not occur anywhere else within the
  197.    Pilot or its communications. */
  198.    
  199. /* Notice: These conversion functions apply a possibly incorrect timezone
  200.    correction. They use the local time on the UNIX box, and transmit this
  201.    directly to the Pilot. This assumes that the Pilot has the same local
  202.    time. If the Pilot is communicating from a different timezone, this is
  203.    not necessarily correct.
  204.    
  205.    It would be possible to compare the current time on the Pilot with the
  206.    current time on the UNIX box, and use that as the timezone offset, but
  207.    this would break if the Pilot had the wrong time, or one or the either
  208.    didn't have the proper local (wall) time.
  209.    
  210.    In any case, since the (possibly incorrect) timezone correction is
  211.    applied both way, there is no immediate problem.
  212.                                                                    -- KJA
  213.    */
  214.    
  215. static time_t dlp_ptohdate(unsigned const char * data)
  216. {
  217.         struct tm t;
  218.         
  219.         t.tm_sec   = (int)data[6];
  220.         t.tm_min   = (int)data[5];
  221.         t.tm_hour  = (int)data[4];
  222.         t.tm_mday  = (int)data[3];
  223.         t.tm_mon   = (int)data[2]-1;
  224.         t.tm_year  = ((data[0]<<8) | data[1])-1900;
  225.         t.tm_wday  = 0;
  226.         t.tm_yday  = 0;
  227.         t.tm_isdst = -1;
  228.         
  229.         return mktime(&t);
  230. }
  231.  
  232. static void dlp_htopdate(time_t time, unsigned char * data) /*@+ptrnegate@*/
  233. {
  234.         struct tm * t = localtime(&time);
  235.         int y;
  236.  
  237.         if (!t)
  238.           abort();
  239.         
  240.         y = t->tm_year+1900;
  241.         
  242.         data[7] = (unsigned char)0; /* packing spacer */
  243.         data[6] = (unsigned char)t->tm_sec;
  244.         data[5] = (unsigned char)t->tm_min;
  245.         data[4] = (unsigned char)t->tm_hour;
  246.         data[3] = (unsigned char)t->tm_mday;
  247.         data[2] = (unsigned char)(t->tm_mon+1);
  248.         data[0] = (unsigned char)((y >> 8) & 0xff);
  249.         data[1] = (unsigned char)((y >> 0) & 0xff);
  250.         
  251.         return;
  252. }
  253.  
  254. int dlp_GetSysDateTime(int sd, time_t * t)
  255. {
  256.   unsigned char buf[8];
  257.   int result;
  258.   
  259.   Trace(GetSysDateTime);
  260.   
  261.   result = dlp_exec(sd, 0x13, 0x20, 0, 0, buf, 8);
  262.   
  263.   Expect(8);
  264.   
  265.   *t = dlp_ptohdate(buf);
  266.  
  267. #ifdef DLP_TRACE
  268.   if (dlp_trace) {
  269.     fprintf(stderr, "   Read: Time: %s", ctime(t));
  270.   }
  271. #endif
  272.   
  273.   return result;
  274. }
  275.  
  276. int dlp_SetSysDateTime(int sd, time_t time)
  277. {
  278.   unsigned char buf[8];
  279.   int result;
  280.   dlp_htopdate(time, buf);
  281.  
  282.   Trace(ReadSysInfo);
  283.  
  284. #ifdef DLP_TRACE
  285.   if (dlp_trace) {
  286.     fprintf(stderr, "  Wrote: Time: %s", ctime(&time));
  287.   }
  288. #endif
  289.   
  290.   result = dlp_exec(sd, 0x14, 0x20, buf, 8, 0, 0);
  291.   
  292.   Expect(0);
  293.   
  294.   return result;
  295. }
  296.  
  297. /* begin struct SI
  298.  *  Byte    number        byte(0)
  299.  *  Byte    more        byte(1)
  300.  *  Byte    unused        byte(2)
  301.  *  Byte    count        byte(3)
  302.  *  Byte    totalSize        byte(4)
  303.  *  Byte    cardNo        byte(5)
  304.  *  Word    cardVersion        short(6)
  305.  *  DlpDateTimeType crDate    date(8)
  306.  *  DWord   romSize        long(16)
  307.  *  DWord   ramSize        long(20)
  308.  *  DWord   freeRam        long(24)
  309.  *  Byte    cardNameSize    byte(28)
  310.  *  Byte    cardManufSize    byte(29)
  311.  *  Char[0] cardNameAndManuf    byte(30)
  312.  * struct read access */
  313. #define SI_number(ptr)        get_byte((ptr)+0)
  314. #define SI_more(ptr)        get_byte((ptr)+1)
  315. #define SI_unused(ptr)        get_byte((ptr)+2)
  316. #define SI_count(ptr)        get_byte((ptr)+3)
  317. #define SI_totalSize(ptr)        get_byte((ptr)+4)
  318. #define SI_cardNo(ptr)        get_byte((ptr)+5)
  319. #define SI_cardVersion(ptr)        get_short((ptr)+6)
  320. #define SI_crDate(ptr)        get_date((ptr)+8)
  321. #define SI_romSize(ptr)        get_long((ptr)+16)
  322. #define SI_ramSize(ptr)        get_long((ptr)+20)
  323. #define SI_freeRam(ptr)        get_long((ptr)+24)
  324. #define SI_cardNameSize(ptr)        get_byte((ptr)+28)
  325. #define SI_cardManufSize(ptr)        get_byte((ptr)+29)
  326. #define SI_cardNameAndManuf(ptr,idx)    get_byte((ptr)+30+1*(idx))
  327. #define ptr_SI_cardNameAndManuf(ptr,idx)    ((ptr)+30+1*(idx))
  328. #define sizeof_SI        (30)
  329.  /* end struct SI */
  330.  
  331. /* begin struct SIRequest
  332.  *  Byte    cardNo        byte(0)
  333.  *  Byte    unused        byte(1)
  334.  * struct write access */
  335. #define SIRequest_cardNo(ptr,val)        set_byte((ptr)+0,(val))
  336. #define SIRequest_unused(ptr,val)        set_byte((ptr)+1,(val))
  337. #define sizeof_SIRequest        (2)
  338.  /* end struct SIRequest */
  339.  
  340. int dlp_ReadStorageInfo(int sd, int cardno, struct CardInfo * c)
  341. {
  342.   int result;
  343.   int len1,len2;
  344.   
  345.   SIRequest_cardNo(dlp_buf, cardno);
  346.   SIRequest_unused(dlp_buf, 0);
  347.   
  348.   Trace(ReadStorageInfo);
  349.   
  350. #ifdef DLP_TRACE
  351.   if (dlp_trace) {
  352.     fprintf(stderr, " Wrote: Cardno: %d\n", cardno);
  353.   }
  354. #endif  
  355.   
  356.   result = dlp_exec(sd, 0x15, 0x20, dlp_buf, 2, dlp_buf, 256+26);
  357.   
  358.   c->more = 0;
  359.   
  360.   Expect(sizeof_SI);
  361.   
  362.   c->more = SI_more(dlp_buf) || (SI_count(dlp_buf) > 1);
  363.   
  364.   c->card =    SI_cardNo(dlp_buf);
  365.   c->version =    SI_cardVersion(dlp_buf);
  366.   c->creation = SI_crDate(dlp_buf);
  367.   c->romSize =    SI_romSize(dlp_buf);
  368.   c->ramSize =    SI_ramSize(dlp_buf);
  369.   c->ramFree =    SI_freeRam(dlp_buf);
  370.   
  371.   len1 = SI_cardNameSize(dlp_buf);
  372.   memcpy(c->name, ptr_SI_cardNameAndManuf(dlp_buf,0), len1);
  373.   c->name[len1] = '\0';
  374.   
  375.   len2 = SI_cardManufSize(dlp_buf);
  376.   memcpy(c->manufacturer, ptr_SI_cardNameAndManuf(dlp_buf, len1), len2);
  377.   c->manufacturer[len2] = '\0';
  378.   
  379. #ifdef DLP_TRACE
  380.   if (dlp_trace) {  
  381.     fprintf(stderr, "  Read: Cardno: %d, Card Version: %d, Creation time: %s",
  382.       c->card, c->version, ctime(&c->creation));
  383.     fprintf(stderr, "        Total ROM: %lu, Total RAM: %lu, Free RAM: %lu\n",
  384.       c->romSize, c->ramSize, c->ramFree);
  385.     fprintf(stderr, "        Card name: '%s'\n", c->name);
  386.     fprintf(stderr, "        Manufacturer name: '%s'\n", c->manufacturer);
  387.     fprintf(stderr, "        More: %s\n", c->more ? "Yes" : "No");
  388.   }
  389. #endif
  390.   
  391.   return result;
  392. }
  393.  
  394.  
  395. int dlp_ReadSysInfo(int sd, struct SysInfo * s)
  396. {
  397.   int result;
  398.   
  399.   Trace(ReadSysInfo);
  400.   
  401.   result = dlp_exec(sd, 0x12, 0x20, NULL, 0, dlp_buf, 256);
  402.   
  403.   Expect(10);
  404.   
  405.   s->romVersion = get_long(dlp_buf);
  406.   s->locale = get_long(dlp_buf+4);
  407.   /* dlp_buf+8 is a filler byte */
  408.   s->nameLength = get_byte(dlp_buf+9);
  409.   memcpy(s->name, dlp_buf+10, s->nameLength);
  410.   s->name[s->nameLength] = '\0';
  411.  
  412. #ifdef DLP_TRACE
  413.   if (dlp_trace) {    
  414.     fprintf(stderr, "  Read: ROM Version: 0x%8.8lX, Localization ID: 0x%8.8lX\n",
  415.       (unsigned long)s->romVersion, (unsigned long)s->locale);
  416.     fprintf(stderr, "        Name '%s'\n", s->name);
  417.   }
  418. #endif
  419.   
  420.   return result;
  421. }
  422.  
  423. int dlp_ReadDBList(int sd, int cardno, int flags, int start, struct DBInfo * info)
  424. {
  425.   int result;
  426.  
  427.   dlp_buf[0] = (unsigned char)flags;
  428.   dlp_buf[1] = (unsigned char)cardno;
  429.   set_short(dlp_buf+2, start);
  430.  
  431.   Trace(ReadDBList);
  432.  
  433. #ifdef DLP_TRACE  
  434.   if (dlp_trace) {  
  435.     fprintf(stderr, " Wrote: Cardno: %d, Start: %d, Flags:", cardno, start);
  436.     if (flags & dlpDBListROM)
  437.       fprintf(stderr, " ROM");
  438.     if (flags & dlpDBListRAM)
  439.       fprintf(stderr, " RAM");
  440.     if (!flags)
  441.       fprintf(stderr, " None");
  442.     fprintf(stderr, " (0x%2.2X)\n", flags);
  443.   }
  444. #endif
  445.   
  446.   result = dlp_exec(sd, 0x16, 0x20, dlp_buf, 4, dlp_buf, 48+32);
  447.   
  448.   info->more = 0;
  449.   
  450.   Expect(48);
  451.   
  452.   info->more = get_byte(dlp_buf+2);
  453.   if (pi_version(sd) > 0x0100) /* PalmOS 2.0 has additional flag */
  454.     info->miscFlags = get_byte(dlp_buf+5);
  455.   else
  456.     info->miscFlags = 0;
  457.   info->flags = get_short(dlp_buf+6);
  458.   info->type = get_long(dlp_buf+8);
  459.   info->creator = get_long(dlp_buf+12);
  460.   info->version = get_short(dlp_buf+16);
  461.   info->modnum = get_long(dlp_buf+18);
  462.   info->createDate = get_date(dlp_buf+22);
  463.   info->modifyDate = get_date(dlp_buf+30);
  464.   info->backupDate = get_date(dlp_buf+38);
  465.   info->index = get_short(dlp_buf+46);
  466.   strncpy(info->name, (char*)dlp_buf+48, 32);
  467.   info->name[32] = '\0';
  468.  
  469. #ifdef DLP_TRACE
  470.   if (dlp_trace) {  
  471.     fprintf(stderr, "  Read: Name: '%s', Version: %d, More: %s\n",
  472.       info->name, info->version, info->more ? "Yes" : "No");
  473.     fprintf(stderr, "        Creator: '%s'", printlong(info->creator));
  474.     fprintf(stderr, ", Type: '%s', Flags:", printlong(info->type));
  475.     if (info->flags & dlpDBFlagResource)
  476.       fprintf(stderr, " Resource");
  477.     if (info->flags & dlpDBFlagReadOnly)
  478.       fprintf(stderr, " ReadOnly");
  479.     if (info->flags & dlpDBFlagAppInfoDirty)
  480.       fprintf(stderr, " AppInfoDirty");
  481.     if (info->flags & dlpDBFlagBackup)
  482.       fprintf(stderr, " Backup");
  483.     if (info->flags & dlpDBFlagReset)
  484.       fprintf(stderr, " Reset");
  485.     if (info->flags & dlpDBFlagNewer)
  486.       fprintf(stderr, " Newer");
  487.     if (info->flags & dlpDBFlagOpen)
  488.       fprintf(stderr, " Open");
  489.     if (!info->flags)
  490.       fprintf(stderr, " None");
  491.     fprintf(stderr, " (0x%2.2X)\n", info->flags);
  492.     fprintf(stderr, "        Modnum: %ld, Index: %d, Creation date: %s",
  493.       info->modnum, info->index, ctime(&info->createDate));
  494.     fprintf(stderr, "        Modification date: %s", ctime(&info->modifyDate));
  495.     fprintf(stderr, "        Backup date: %s", ctime(&info->backupDate));
  496.   }
  497. #endif
  498.     
  499.   return result;
  500. }
  501.  
  502. int dlp_FindDBInfo(int sd, int cardno, int start, char * dbname, unsigned long type, unsigned long creator, struct DBInfo * info)
  503. {
  504.   int i;
  505.   
  506.   /* This function does not match any DLP layer function, but is intended as
  507.      a shortcut for programs looking for databases. It uses a fairly
  508.      byzantine mechanism for ordering the RAM databases before the ROM ones.
  509.      You must feed the "index" slot from the returned info in as start the
  510.      next time round. */
  511.   
  512.   if (start < 0x1000) {
  513.     i=start;
  514.     while(dlp_ReadDBList(sd, cardno, 0x80, i, info)>0) {
  515.       if( 
  516.          ((!dbname) || (strcmp(info->name,dbname)==0)) &&
  517.          ((!type) || (info->type==type)) &&
  518.          ((!creator) || (info->creator==creator))
  519.         )
  520.         goto found;
  521.       i=info->index+1;
  522.     }
  523.     start = 0x1000;
  524.   }
  525.   
  526.   i=start & 0xFFF;
  527.   while(dlp_ReadDBList(sd, cardno, 0x40, i, info)>0) {
  528.     if( 
  529.        ((!dbname) || (strcmp(info->name,dbname)==0)) &&
  530.        ((!type) || (info->type==type)) &&
  531.        ((!creator) || (info->creator==creator))
  532.       ) {
  533.       info->index |= 0x1000;
  534.       goto found;
  535.     }
  536.     i=info->index+1;
  537.   }
  538.   
  539.   return -1;
  540.  
  541. found:
  542.  
  543.   return 0;
  544. }
  545.  
  546. int dlp_OpenDB(int sd, int cardno, int mode, char * name, int * dbhandle)
  547. {
  548.   unsigned char handle;
  549.   int result;
  550.  
  551.   dlp_buf[0] = (unsigned char)cardno;
  552.   dlp_buf[1] = (unsigned char)mode;
  553.   strcpy((char*)dlp_buf+2, name);
  554.  
  555.   Trace(OpenDB);
  556.  
  557. #ifdef DLP_TRACE  
  558.   if (dlp_trace) {  
  559.     fprintf(stderr, " Wrote: Cardno: %d, Name: '%s', Mode:", cardno, name);
  560.     if (mode & dlpOpenRead)
  561.       fprintf(stderr, " Read");
  562.     if (mode & dlpOpenWrite)
  563.       fprintf(stderr, " Write");
  564.     if (mode & dlpOpenExclusive)
  565.       fprintf(stderr, " Exclusive");
  566.     if (mode & dlpOpenSecret)
  567.       fprintf(stderr, " Secret");
  568.     if (!mode)
  569.       fprintf(stderr, " None");
  570.     fprintf(stderr, " (0x%2.2X)\n", mode);
  571.   }
  572. #endif
  573.   
  574.   result = dlp_exec(sd, 0x17, 0x20, &dlp_buf[0], strlen(name)+3, &handle, 1);
  575.   
  576.   Expect(1);
  577.   
  578.   *dbhandle = (int)handle;
  579.  
  580. #ifdef DLP_TRACE  
  581.   if (dlp_trace) {  
  582.     fprintf(stderr, "  Read: Handle: %d\n", (int)handle);
  583.   }
  584. #endif
  585.   
  586.   return result;
  587. }
  588.  
  589.  
  590.  
  591. int dlp_DeleteDB(int sd, int card, const char * name)
  592. {
  593.   int result;
  594.   
  595.   dlp_buf[0] = (unsigned char)card;
  596.   dlp_buf[1] = (unsigned char)0;
  597.   strcpy((char*)dlp_buf+2, name);
  598.  
  599.   Trace(DeleteDB);
  600.  
  601. #ifdef DLP_TRACE  
  602.   if (dlp_trace) {  
  603.     fprintf(stderr, " Wrote: Cardno: %d, Name: '%s'\n", card, name);
  604.   }
  605. #endif
  606.   
  607.   result = dlp_exec(sd, 0x1A, 0x20, dlp_buf, 2+strlen(name)+1, 0, 0);
  608.   
  609.   Expect(0);
  610.   
  611.   return result;
  612. }
  613.  
  614. int dlp_CreateDB(int sd, long creator, long type, int cardno, 
  615.                  int flags, int version, const char * name, int * dbhandle)
  616. {
  617.   unsigned char handle;
  618.   int result;
  619.  
  620.   set_long(dlp_buf, creator);
  621.   set_long(dlp_buf+4, type);
  622.   set_byte(dlp_buf+8, cardno);
  623.   set_byte(dlp_buf+9, 0);
  624.   set_short(dlp_buf+10, flags);
  625.   set_short(dlp_buf+12, version);
  626.   strcpy((char*)dlp_buf+14, name);
  627.   
  628.   Trace(CreateDB);
  629.  
  630. #ifdef DLP_TRACE  
  631.   if (dlp_trace) {  
  632.     fprintf(stderr, " Wrote: Card: %d, version: %d, name '%s'\n", cardno, version, name);
  633.     fprintf(stderr, "        DB Flags:");
  634.     if (flags & dlpDBFlagResource)
  635.       fprintf(stderr, " Resource");
  636.     if (flags & dlpDBFlagReadOnly)
  637.       fprintf(stderr, " ReadOnly");
  638.     if (flags & dlpDBFlagAppInfoDirty)
  639.       fprintf(stderr, " AppInfoDirty");
  640.     if (flags & dlpDBFlagBackup)
  641.       fprintf(stderr, " Backup");
  642.     if (flags & dlpDBFlagReset)
  643.       fprintf(stderr, " Reset");
  644.     if (flags & dlpDBFlagNewer)
  645.       fprintf(stderr, " Newer");
  646.     if (flags & dlpDBFlagOpen)
  647.       fprintf(stderr, " Open");
  648.     if (!flags)
  649.       fprintf(stderr, " None");
  650.     fprintf(stderr, " (0x%2.2X), Creator: '%s'", flags, printlong(creator));
  651.     fprintf(stderr, ", Type: '%s'\n", printlong(type));
  652.   }
  653. #endif  
  654.  
  655.   result = dlp_exec(sd, 0x18, 0x20, dlp_buf, 14+strlen(name)+1, &handle, 1);
  656.   
  657.   Expect(1);
  658.   
  659.   if (dbhandle)
  660.     *dbhandle = (int)handle;
  661.  
  662. #ifdef DLP_TRACE
  663.   if (dlp_trace) {  
  664.     fprintf(stderr, "  Read: Handle: %d\n", (int)handle);
  665.   }
  666. #endif
  667.  
  668.   return result;
  669. }
  670.  
  671.  
  672. int dlp_CloseDB(int sd, int dbhandle)
  673. {
  674.   unsigned char handle = (unsigned char)dbhandle;
  675.   int result;
  676.  
  677.   Trace(CloseDB);
  678.  
  679. #ifdef DLP_TRACE  
  680.   if (dlp_trace) {  
  681.     fprintf(stderr, " Wrote: Handle: %d\n", dbhandle);
  682.   }
  683. #endif
  684.   
  685.   result = dlp_exec(sd, 0x19, 0x20, &handle, 1, 0, 0);
  686.  
  687.   Expect(0);
  688.   
  689.   return result;
  690. }
  691.  
  692. int dlp_CloseDB_All(int sd)
  693. {
  694.   int result;
  695.  
  696.   Trace(CloseDB_all);
  697.   
  698.   result = dlp_exec(sd, 0x19, 0x21, 0, 0, 0, 0);
  699.   
  700.   Expect(0);
  701.   
  702.   return result;
  703. }
  704.  
  705. int dlp_CallApplication(int sd, unsigned long creator, unsigned long type, int action, 
  706.                         int length, void * data,
  707.                         unsigned long * retcode, int maxretlen, int * retlen, void * retdata)
  708. {
  709.   int result;
  710.   int version = pi_version(sd);
  711.   
  712.   if (version >= 0x0101) { /* PalmOS 2.0 call encoding */
  713.     set_long(dlp_buf+0, creator);
  714.     set_long(dlp_buf+4, type);
  715.     set_short(dlp_buf+8, action);
  716.     set_long(dlp_buf+10, length);
  717.     set_long(dlp_buf+14, 0);
  718.     set_long(dlp_buf+18, 0);
  719.     
  720.     if (length+22 > DLP_BUF_SIZE) {
  721.         fprintf(stderr, "Data too large\n");
  722.         return -131;
  723.     }
  724.     
  725.     memcpy(dlp_buf+22, data, length);
  726.  
  727.     Trace(CallApplicationV2);
  728.  
  729. #ifdef DLP_TRACE  
  730.     if (dlp_trace) {  
  731.       fprintf(stderr, " Wrote: Creator: '%s',", printlong(creator));
  732.       fprintf(stderr, " Type: '%s', Action code: %d, and %d bytes of data:\n",
  733.         printlong(type), action, length);
  734.       dumpdata(data, length);
  735.     }
  736. #endif
  737.  
  738.     result = dlp_exec(sd, 0x28, 0x21, dlp_buf, 22 + length, dlp_buf, 0xffff);
  739.   
  740.     Expect(16);
  741.   
  742.     if (retcode)
  743.       *retcode = get_long(dlp_buf);
  744.     
  745.     result -= 16;
  746.   
  747.     if (retlen)
  748.       *retlen = result;
  749.     if (retdata)
  750.       memcpy(retdata, dlp_buf+16, result > maxretlen ? maxretlen : result);
  751.   
  752. #ifdef DLP_TRACE  
  753.     if (dlp_trace) {  
  754.       fprintf(stderr, "  Read: Result: %lu (0x%8.8lX), and %d bytes:\n",
  755.         get_long(dlp_buf), get_long(dlp_buf+4), result);
  756.       dumpdata(dlp_buf+16,result);
  757.     }
  758. #endif
  759.   
  760.     return result;
  761.  
  762.  
  763.   } else { /* PalmOS 1.0 call encoding */
  764.     set_long(dlp_buf+0, creator);
  765.     set_short(dlp_buf+4, action);
  766.     set_short(dlp_buf+6, length);
  767.     memcpy(dlp_buf+6, data, length);
  768.  
  769.     Trace(CallApplicationV10);
  770.  
  771. #ifdef DLP_TRACE
  772.     if (dlp_trace) {  
  773.       fprintf(stderr, " Wrote: Creator: '%s', Action code: %d, and %d bytes of data:\n",
  774.         printlong(creator), action, length);
  775.       dumpdata(data, length);
  776.     }
  777. #endif
  778.  
  779.     result = dlp_exec(sd, 0x28, 0x20 , dlp_buf, 8, dlp_buf, 0xffff);
  780.   
  781.     Expect(6);
  782.   
  783.     if (retcode)
  784.       *retcode = get_short(dlp_buf+2);
  785.     
  786.     result -= 6;
  787.   
  788.     if (retlen)
  789.       *retlen = result;
  790.     if (retdata)
  791.       memcpy(retdata, dlp_buf+6, result > maxretlen ? maxretlen : result);
  792.   
  793. #ifdef DLP_TRACE  
  794.     if (dlp_trace) {  
  795.       fprintf(stderr, "  Read: Action: %d, Result: %d (0x%4.4X), and %d bytes:\n",
  796.         get_short(dlp_buf), get_short(dlp_buf+2), get_short(dlp_buf+2), result);
  797.       dumpdata(dlp_buf+6, result);
  798.     }
  799. #endif
  800.   
  801.     return result;
  802.  
  803.   }  
  804.   
  805. }
  806.  
  807. int dlp_ResetSystem(int sd)
  808. {
  809.   int result;
  810.  
  811.   Trace(ResetSystem);
  812.   
  813.   result = dlp_exec(sd, 0x29, 0, 0, 0, 0, 0);
  814.   
  815.   Expect(0);
  816.  
  817.   return result;
  818. }
  819.  
  820. int dlp_AddSyncLogEntry(int sd, char * entry)
  821.   int result;
  822.  
  823.   Trace(AddSyncLogEntry);
  824.   
  825. #ifdef DLP_TRACE  
  826.   if (dlp_trace) {  
  827.     fprintf(stderr," Wrote: Entry:\n");
  828.     dumpdata((unsigned char *)entry,strlen(entry));
  829.   }
  830. #endif
  831.  
  832.   result = dlp_exec(sd, 0x2A, 0x20, (unsigned char*)entry, strlen(entry), 0, 0);
  833.  
  834.   Expect(0);
  835.   
  836.   return result;
  837. }
  838.  
  839. int dlp_ReadOpenDBInfo(int sd, int dbhandle, int * records)
  840. {
  841.   unsigned char buf[2];
  842.   int result;
  843.  
  844.   Trace(ReadOpenDBInfo);
  845.  
  846. #ifdef DLP_TRACE
  847.   if (dlp_trace) {  
  848.     fprintf(stderr, " Wrote: Handle: %d\n", dbhandle);
  849.   }
  850. #endif
  851.   
  852.   set_byte(dlp_buf, (unsigned char)dbhandle);
  853.   result = dlp_exec(sd, 0x2B, 0x20, dlp_buf, 1, buf, 2);
  854.  
  855.   Expect(2);
  856.   
  857.   if (records)
  858.     *records = get_short(buf);
  859.       
  860. #ifdef DLP_TRACE
  861.   if (dlp_trace) {  
  862.     fprintf(stderr, "  Read: %d records\n", get_short(buf));
  863.   }
  864. #endif
  865.   
  866.   return result;
  867. }
  868.  
  869. int dlp_MoveCategory(int sd, int handle, int fromcat, int tocat)
  870. {
  871.   int result;
  872.   
  873.   set_byte(dlp_buf+0, handle);
  874.   set_byte(dlp_buf+1, fromcat);
  875.   set_byte(dlp_buf+2, tocat);
  876.   set_byte(dlp_buf+3, 0);
  877.  
  878.   Trace(MoveCategory);
  879.  
  880. #ifdef DLP_TRACE  
  881.   if (dlp_trace) {  
  882.     fprintf(stderr, " Wrote: Handle: %d, From: %d, To: %d\n", handle, fromcat, tocat);
  883.   }
  884. #endif
  885.   
  886.   result = dlp_exec(sd, 0x2C, 0x20, dlp_buf, 4, 0, 0);
  887.   
  888.   Expect(0);
  889.   
  890.   return result;
  891. }
  892.  
  893.  
  894. int dlp_OpenConduit(int sd)
  895. {
  896.   int result;
  897.  
  898.   Trace(OpenConduit);
  899.  
  900.   result = dlp_exec(sd, 0x2E, 0, 0, 0, 0, 0);
  901.  
  902.   Expect(0);
  903.   
  904.   return result;
  905. }
  906.  
  907. int dlp_EndOfSync(int sd, int status)
  908. {
  909.   int result;
  910.   struct pi_socket * ps;
  911.   
  912.   set_short(dlp_buf, status);
  913.  
  914.   Trace(EndOfSync);
  915.   
  916.   result = dlp_exec(sd, 0x2F, 0x20, dlp_buf, 2, 0, 0);
  917.  
  918.   Expect(0);
  919.   
  920.   /* Messy code to set end-of-sync flag on socket 
  921.      so pi_close won't do it for us */
  922.   if (result == 0)
  923.     if ( (ps = find_pi_socket(sd)) )
  924.       ps->connected |= 2;
  925.   
  926.   return result;
  927. }
  928.  
  929. int dlp_AbortSync(int sd) {
  930.   struct pi_socket * ps;
  931.  
  932. #ifdef DLP_TRACE
  933.   if (dlp_trace) {  
  934.     fprintf(stderr, "DLP %d: AbortSync\nResult: Whatever\n", sd);
  935.   }
  936. #endif
  937.   
  938.   /* Set end-of-sync flag on socket so pi_close won't do a dlp_EndOfSync */
  939.   if ( (ps = find_pi_socket(sd)) )
  940.     ps->connected |= 2;
  941.  
  942.   return pi_close(sd);
  943. }
  944.  
  945. int dlp_WriteUserInfo(int sd, struct PilotUser *User)
  946. {
  947.   int result;
  948.  
  949.   Trace(WriteUserInfo);
  950.  
  951. #ifdef DLP_TRACE
  952.   if (dlp_trace) {  
  953.     fprintf(stderr, " Wrote: UID: 0x%8.8lX, VID: 0x%8.8lX, PCID: 0x%8.8lX\n", 
  954.       User->userID, User->viewerID, User->lastSyncPC);
  955.     fprintf(stderr, "        Last sync date: %s", ctime(&User->lastSyncDate));
  956.     fprintf(stderr, "        Successful sync date: %s", ctime(&User->successfulSyncDate));
  957.     fprintf(stderr, "        User name '%s'\n", User->username);
  958.   }
  959. #endif
  960.   
  961.   set_long(dlp_buf, User->userID);
  962.   set_long(dlp_buf+4, User->viewerID);
  963.   set_long(dlp_buf+8, User->lastSyncPC);
  964.   set_date(dlp_buf+12, User->lastSyncDate);
  965.   set_byte(dlp_buf+20, 0xff);
  966.   set_byte(dlp_buf+21, strlen(User->username)+1);
  967.   strcpy((char*)dlp_buf+22, User->username);
  968.  
  969.   result = dlp_exec(sd, 0x11, 0x20, dlp_buf, 22+strlen(User->username)+1, NULL, 0);
  970.   
  971.   Expect(0);
  972.   
  973.   return result;
  974. }
  975.                         
  976. int dlp_ReadUserInfo(int sd, struct PilotUser* User)
  977. {
  978.   int result;
  979.   int userlen;
  980.  
  981.   Trace(ReadUserInfo);
  982.  
  983.   result = dlp_exec(sd, 0x10, 0x00, NULL, 0, dlp_buf, DLP_BUF_SIZE);
  984.  
  985.   Expect(30);
  986.  
  987.   userlen = get_byte(dlp_buf+28);
  988.  
  989.   User->userID = get_long(dlp_buf);
  990.   User->viewerID = get_long(dlp_buf+4);
  991.   User->lastSyncPC = get_long(dlp_buf+8);
  992.   User->successfulSyncDate = get_date(dlp_buf+12);
  993.   User->lastSyncDate = get_date(dlp_buf+20);
  994.   User->passwordLength = get_byte(dlp_buf+29);
  995.   memcpy(User->username, dlp_buf+30, userlen);
  996.   User->username[userlen] = '\0';
  997.   memcpy(User->password, dlp_buf+30+userlen, User->passwordLength);
  998.  
  999. #ifdef DLP_TRACE
  1000.   if (dlp_trace) {  
  1001.     fprintf(stderr, "  Read: UID: 0x%8.8lX, VID: 0x%8.8lX, PCID: 0x%8.8lX\n", 
  1002.       User->userID, User->viewerID, User->lastSyncPC);
  1003.     fprintf(stderr, "        Last sync date: %s", ctime(&User->lastSyncDate));
  1004.     fprintf(stderr, "        Successful sync date: %s", ctime(&User->successfulSyncDate));
  1005.     fprintf(stderr, "        User name '%s'", User->username);
  1006.     if (User->passwordLength) {
  1007.       fprintf(stderr, ", Password of %d bytes:\n", User->passwordLength);
  1008.       dumpdata((unsigned char *)User->password,User->passwordLength);
  1009.     }
  1010.     else
  1011.       fprintf(stderr, ", No password\n");
  1012.   }
  1013. #endif
  1014.  
  1015.   return result;
  1016. }
  1017.  
  1018. int dlp_ReadNetSyncInfo(int sd, struct NetSyncInfo * i)
  1019. {
  1020.   int result;
  1021.   int p;
  1022.   
  1023.   if (pi_version(sd)<0x0101)
  1024.     return -129; /* This call only functions under PalmOS 2.0 */
  1025.  
  1026.   Trace(ReadNetSyncInfo);
  1027.  
  1028.   result = dlp_exec(sd, 0x36, 0x20, NULL, 0, dlp_buf, DLP_BUF_SIZE);
  1029.  
  1030.   Expect(24);
  1031.   
  1032.  
  1033.   i->lanSync = get_byte(dlp_buf);
  1034.   p = 24;
  1035.  
  1036.   i->hostName[0] = 0;
  1037.   memcpy(i->hostName, dlp_buf+p, get_short(dlp_buf+18));
  1038.   p += get_short(dlp_buf+18);
  1039.  
  1040.   i->hostAddress[0] = 0;
  1041.   memcpy(i->hostAddress, dlp_buf+p, get_short(dlp_buf+20));
  1042.   p += get_short(dlp_buf+20);
  1043.  
  1044.   i->hostSubnetMask[0] = 0;
  1045.   memcpy(i->hostSubnetMask, dlp_buf+p, get_short(dlp_buf+22));
  1046.   p += get_short(dlp_buf+22);
  1047.  
  1048. #ifdef DLP_TRACE
  1049.   if (dlp_trace) {  
  1050.     fprintf(stderr, "  Read: Active: %d\n", get_byte(dlp_buf));
  1051.     fprintf(stderr, "        PC hostname: '%s', address '%s', mask '%s'\n",
  1052.       i->hostName, i->hostAddress, i->hostSubnetMask);
  1053.   }
  1054. #endif
  1055.  
  1056.   return result;
  1057. }
  1058.  
  1059. int dlp_WriteNetSyncInfo(int sd, struct NetSyncInfo * i)
  1060. {
  1061.   int result;
  1062.   int p;
  1063.   
  1064.   if (pi_version(sd)<0x0101)
  1065.     return -129;
  1066.  
  1067.   Trace(WriteNetSyncInfo);
  1068.  
  1069. #ifdef DLP_TRACE
  1070.   if (dlp_trace) {  
  1071.     fprintf(stderr, "  Wrote: Active: %d\n", get_byte(dlp_buf));
  1072.     fprintf(stderr, "        PC hostname: '%s', address '%s', mask '%s'\n",
  1073.       i->hostName, i->hostAddress, i->hostSubnetMask);
  1074.   }
  1075. #endif
  1076.   
  1077.   set_byte(dlp_buf, 0x80|0x40|0x20|0x10); /* Change all settings */
  1078.   set_byte(dlp_buf+1, i->lanSync);
  1079.   set_long(dlp_buf+2, 0);  /* Reserved1 */
  1080.   set_long(dlp_buf+6, 0);  /* Reserved2 */
  1081.   set_long(dlp_buf+10, 0); /* Reserved3 */
  1082.   set_long(dlp_buf+14, 0); /* Reserved4 */
  1083.   set_short(dlp_buf+18, strlen(i->hostName)+1);
  1084.   set_short(dlp_buf+20, strlen(i->hostAddress)+1);
  1085.   set_short(dlp_buf+22, strlen(i->hostSubnetMask)+1);
  1086.   p = 24;
  1087.   strcpy((char *)dlp_buf+p, i->hostName);
  1088.   p += strlen(i->hostName)+1;
  1089.   strcpy((char *)dlp_buf+p, i->hostAddress);
  1090.   p += strlen(i->hostAddress)+1;
  1091.   strcpy((char *)dlp_buf+p, i->hostSubnetMask);
  1092.   p += strlen(i->hostSubnetMask)+1;
  1093.   
  1094.   result = dlp_exec(sd, 0x37, 0x20, dlp_buf, p, dlp_buf, DLP_BUF_SIZE);
  1095.  
  1096.   Expect(0);
  1097.  
  1098.   return result;
  1099. }
  1100.  
  1101. int dlp_RPC(int sd, struct RPC_params * p, unsigned long * result)
  1102. {
  1103.   int i;
  1104.   unsigned char * c;
  1105.   
  1106.   /* RPC through DLP breaks all the rules and isn't well documented to boot */
  1107.   
  1108.   long D0=0,A0=0;
  1109.   int err;
  1110.   
  1111.   dlp_buf[0] = 0x2D;
  1112.   dlp_buf[1] = 1;
  1113.   dlp_buf[2] = 0; /* Unknown filler */
  1114.   dlp_buf[3] = 0;
  1115.  
  1116.   InvertRPC(p);
  1117.   
  1118.   set_short(dlp_buf+4, p->trap);
  1119.   set_long(dlp_buf+6, D0);
  1120.   set_long(dlp_buf+10, A0);
  1121.   set_short(dlp_buf+14, p->args);
  1122.     
  1123.   c = dlp_buf+16;
  1124.   for(i=p->args-1;i>=0;i--) {
  1125.     set_byte(c, p->param[i].byRef); c++;
  1126.     set_byte(c, p->param[i].size); c++;
  1127.     if(p->param[i].data)
  1128.       memcpy(c, p->param[i].data, p->param[i].size);
  1129.     c += p->param[i].size;
  1130.     if(p->param[i].size & 1)
  1131.       *c++ = 0;
  1132.   }
  1133.  
  1134.   pi_write(sd, dlp_buf, c-dlp_buf);
  1135.   
  1136.   err = 0;
  1137.   
  1138.   if(p->reply) {
  1139.     int l = pi_read(sd, dlp_buf, c-dlp_buf+2);
  1140.  
  1141.     if (l < 0)
  1142.       err = l;
  1143.     else if (l < 6) 
  1144.       err = -1;
  1145.     else if (dlp_buf[0] != 0xAD)
  1146.       err = -2;
  1147.     else if (get_short(dlp_buf+2))
  1148.       err = -get_short(dlp_buf+2);
  1149.     else {
  1150.       D0 = get_long(dlp_buf+8);
  1151.       A0 = get_long(dlp_buf+12);
  1152.       c = dlp_buf+18;
  1153.       for(i=p->args-1;i>=0;i--) {
  1154.         if(p->param[i].byRef && p->param[i].data)
  1155.           memcpy(p->param[i].data, c+2, p->param[i].size);
  1156.         c += 2 + ((p->param[i].size+1)& ~1);
  1157.       }
  1158.     }
  1159.   }
  1160.   
  1161.   UninvertRPC(p);
  1162.   
  1163.   if (result)
  1164.     if(p->reply==RPC_PtrReply)
  1165.       *result = A0;
  1166.     else if (p->reply==RPC_IntReply)
  1167.       *result = D0;
  1168.   
  1169.   return err;
  1170. }
  1171.  
  1172. int dlp_ReadFeature(int sd, unsigned long creator, unsigned int num, unsigned long * feature)
  1173. {
  1174.   int result;
  1175.   
  1176.   if (pi_version(sd)<0x0101) {
  1177.     struct RPC_params p;
  1178.     
  1179.     Trace(ReadFeatureV1);
  1180.  
  1181.     if (feature) {
  1182.       int val;
  1183.       unsigned long result;
  1184.  
  1185. #ifdef DLP_TRACE
  1186.       if (dlp_trace) {  
  1187.         fprintf(stderr, " Wrote: Creator: '%s', Number: %d\n", 
  1188.           printlong(creator), num);
  1189.       }
  1190. #endif
  1191.  
  1192.       *feature = 0x12345678;
  1193.  
  1194.       PackRPC(&p, 0xA27B, RPC_IntReply, 
  1195.          RPC_Long(creator), RPC_Short(num), RPC_LongPtr(feature), RPC_End);
  1196.       
  1197.       val = dlp_RPC(sd, &p, &result);
  1198.       
  1199.  
  1200. #ifdef DLP_TRACE
  1201.       if (dlp_trace) {  
  1202.         if (val < 0)
  1203.           fprintf(stderr, "Result: Error: %s (%d)\n", dlp_errorlist[-val], val); 
  1204.         else if (result)
  1205.           fprintf(stderr, "FtrGet error 0x%8.8lX\n", (unsigned long)result);
  1206.         else
  1207.           fprintf(stderr, "  Read: Feature: 0x%8.8lX\n", (unsigned long)*feature);
  1208.       }
  1209. #endif
  1210.       
  1211.       if (val < 0)
  1212.         return val;
  1213.       if (result)
  1214.         return -result;
  1215.     }
  1216.     
  1217.     return 0;
  1218.   }    
  1219.  
  1220.   Trace(ReadFeatureV2);
  1221.  
  1222. #ifdef DLP_TRACE
  1223.   if (dlp_trace) {  
  1224.     fprintf(stderr, " Wrote: Creator: '%s', Number: %d\n", 
  1225.       printlong(creator), num);
  1226.   }
  1227. #endif
  1228.   
  1229.   set_long(dlp_buf, creator);
  1230.   set_short(dlp_buf+4, num);
  1231.   
  1232.   result = dlp_exec(sd, 0x38, 0x20, dlp_buf, 6, dlp_buf, DLP_BUF_SIZE);
  1233.  
  1234.   Expect(4);
  1235.  
  1236.   if (feature)
  1237.     *feature = (unsigned long)get_long(dlp_buf);
  1238.  
  1239. #ifdef DLP_TRACE
  1240.   if (dlp_trace) {  
  1241.     fprintf(stderr, "  Read: Feature: 0x%8.8lX\n", (unsigned long)get_long(dlp_buf));
  1242.   }
  1243. #endif
  1244.  
  1245.   return result;
  1246. }
  1247.  
  1248. int dlp_ResetLastSyncPC(int sd)
  1249. {
  1250.   struct PilotUser U;
  1251.   int err;
  1252.   
  1253.   if ((err = dlp_ReadUserInfo(sd, &U))<0)
  1254.     return err;
  1255.   U.lastSyncPC = 0;
  1256.   return dlp_WriteUserInfo(sd, &U);
  1257. }
  1258.  
  1259. int dlp_ResetDBIndex(int sd, int dbhandle)
  1260. {
  1261.   int result;
  1262.   struct pi_socket * ps;
  1263.  
  1264.   if ((ps = find_pi_socket(sd)))
  1265.     ps->dlprecord=0;
  1266.  
  1267.   Trace(ResetDBIndex);
  1268.  
  1269. #ifdef DLP_TRACE
  1270.   if (dlp_trace) {  
  1271.     fprintf(stderr, " Wrote: Handle: %d\n", dbhandle);
  1272.   }
  1273. #endif
  1274.   
  1275.   result = dlp_exec(sd, 0x30, 0x20, dlp_buf, 1, NULL, 0);
  1276.   
  1277.   Expect(0);
  1278.  
  1279.   return result;
  1280. }
  1281.  
  1282.  
  1283. int dlp_ReadRecordIDList(int sd, int dbhandle, int sort, 
  1284.                          int start, int max, recordid_t * IDs, int *count)
  1285. {
  1286.   int result, i, ret;
  1287.   unsigned int nbytes;
  1288.   unsigned char * p; 
  1289.   
  1290.   set_byte(dlp_buf,    dbhandle);
  1291.   set_byte(dlp_buf+1,  sort?0x80:0);
  1292.   set_short(dlp_buf+2, start);
  1293.   set_short(dlp_buf+4, max);
  1294.  
  1295.   Trace(ReadRecordIDList);
  1296.  
  1297. #ifdef DLP_TRACE
  1298.   if (dlp_trace) {  
  1299.     fprintf(stderr, " Wrote: Handle: %d, Sort: %s, Start: %d, Max: %d\n",
  1300.       dbhandle, sort ? "Yes" : "No", start, max);
  1301.   }
  1302. #endif
  1303.  
  1304.   nbytes = max * 4 + 2;
  1305.   if (nbytes > DLP_BUF_SIZE)
  1306.     nbytes = DLP_BUF_SIZE;
  1307.   
  1308.   result = dlp_exec(sd, 0x31, 0x20, dlp_buf, 6, dlp_buf, nbytes);
  1309.   
  1310.   Expect(2);
  1311.   
  1312.   ret = get_short(dlp_buf);
  1313.  
  1314. #ifdef DLP_TRACE
  1315.   if (dlp_trace) {  
  1316.     fprintf(stderr, " Read: %d IDs:\n", ret);
  1317.       dumpdata(dlp_buf+2, ret*4);
  1318.   }
  1319. #endif
  1320.  
  1321.   for (i = 0, p = dlp_buf+2; i < ret; i++, p+=4)
  1322.     IDs[i] = get_long(p);
  1323.   
  1324.   if (count)
  1325.     *count = i;
  1326.   
  1327.   return nbytes;
  1328. }
  1329.  
  1330. int dlp_WriteRecord(int sd, int dbhandle, int flags,
  1331.                  recordid_t recID, int catID, void* data, int length, recordid_t * NewID)
  1332. {
  1333.   unsigned char buf[4];
  1334.   int result;
  1335.  
  1336.   set_byte(dlp_buf, dbhandle);
  1337.   set_byte(dlp_buf+1, 0);
  1338.   set_long(dlp_buf+2, recID);
  1339.   set_byte(dlp_buf+6, flags);
  1340.   set_byte(dlp_buf+7, catID);
  1341.   
  1342.   if(length == -1)
  1343.       length = strlen((char*)data)+1;
  1344.  
  1345.   if (length+8 > DLP_BUF_SIZE) {
  1346.     fprintf(stderr, "Data too large\n");
  1347.     return -131;
  1348.   }
  1349.       
  1350.   memcpy(dlp_buf+8, data, length);
  1351.  
  1352.   Trace(WriteRecord);
  1353.  
  1354. #ifdef DLP_TRACE
  1355.   if (dlp_trace) {  
  1356.     fprintf(stderr, " Wrote: Handle: %d, RecordID: 0x%8.8lX, Category: %d\n",
  1357.       dbhandle, (unsigned long)recID, catID);
  1358.     fprintf(stderr, "        Flags:");
  1359.     if (flags & dlpRecAttrDeleted)
  1360.       fprintf(stderr, " Deleted");
  1361.     if (flags & dlpRecAttrDirty)
  1362.       fprintf(stderr, " Dirty");
  1363.     if (flags & dlpRecAttrBusy)
  1364.       fprintf(stderr, " Busy");
  1365.     if (flags & dlpRecAttrSecret)
  1366.       fprintf(stderr, " Secret");
  1367.     if (flags & dlpRecAttrArchived)
  1368.       fprintf(stderr, " Archive");
  1369.     if (!flags)
  1370.       fprintf(stderr, " None");
  1371.     fprintf(stderr, " (0x%2.2X), and %d bytes of data: \n", flags, length);
  1372.     dumpdata(data, length);
  1373.   }
  1374. #endif
  1375.  
  1376.   result = dlp_exec(sd, 0x21, 0x20, dlp_buf, 8+length, buf, 4);
  1377.   
  1378.   Expect(4);
  1379.   
  1380.   if(NewID)
  1381.     if(result == 4)
  1382.       *NewID = get_long(buf); /* New record ID */
  1383.     else
  1384.       *NewID = 0;
  1385.  
  1386. #ifdef DLP_TRACE
  1387.   if (dlp_trace) {  
  1388.     fprintf(stderr, "  Read: Record ID: 0x%8.8lX\n", (unsigned long)get_long(buf));
  1389.   }
  1390. #endif
  1391.       
  1392.   return result;
  1393. }
  1394.  
  1395. int dlp_DeleteRecord(int sd, int dbhandle, int all, recordid_t recID)
  1396. {
  1397.   int result;
  1398.   int flags = all ? 0x80 : 0;
  1399.  
  1400.   set_byte(dlp_buf, dbhandle);
  1401.   set_byte(dlp_buf+1, flags);
  1402.   set_long(dlp_buf+2, recID);
  1403.   
  1404.   Trace(DeleteRecord);
  1405.  
  1406. #ifdef DLP_TRACE
  1407.   if (dlp_trace) {  
  1408.     fprintf(stderr, " Wrote: Handle: %d, RecordID: %8.8lX, All: %s\n",
  1409.       dbhandle, (unsigned long)recID, all ? "Yes" : "No");
  1410.   }
  1411. #endif
  1412.   
  1413.   result = dlp_exec(sd, 0x22, 0x20, dlp_buf, 6, 0, 0);
  1414.   
  1415.   Expect(0);
  1416.   
  1417.   return result;
  1418. }
  1419.  
  1420. int dlp_DeleteCategory(int sd, int dbhandle, int category)
  1421. {
  1422.   int result;
  1423.   int flags = 0x40;
  1424.   
  1425.   if (pi_version(sd) < 0x0101) {
  1426.     /* Emulate if not connected to PalmOS 2.0 */
  1427.     int i,r,cat,attr;
  1428.     recordid_t id;
  1429.  
  1430.     Trace(DeleteCategoryV1);
  1431.  
  1432. #ifdef DLP_TRACE
  1433.     if (dlp_trace) {  
  1434.       fprintf(stderr, " Emulating with: Handle: %d, Category: %d\n",
  1435.         dbhandle, category & 0xff);
  1436.     }
  1437. #endif
  1438.  
  1439.     for(i=0;dlp_ReadRecordByIndex(sd, dbhandle, i, NULL, &id, NULL, &attr, &cat)>=0;i++) {
  1440.       if ((cat != category) || (attr & dlpRecAttrDeleted) || (attr & dlpRecAttrArchived)) 
  1441.         continue;
  1442.       r = dlp_DeleteRecord(sd, dbhandle, 0, id);
  1443.       if (r<0)
  1444.         return r;
  1445.       i--; /* Sigh, deleting the record moves it to the end. */
  1446.     }
  1447.     return 0;
  1448.   }
  1449.  
  1450.   set_byte(dlp_buf, dbhandle);
  1451.   set_byte(dlp_buf+1, flags);
  1452.   set_long(dlp_buf+2, category & 0xff);
  1453.   
  1454.   Trace(DeleteCategoryV2);
  1455.  
  1456. #ifdef DLP_TRACE
  1457.   if (dlp_trace) {  
  1458.     fprintf(stderr, " Wrote: Handle: %d, Category: %d\n",
  1459.       dbhandle, category & 0xff);
  1460.   }
  1461. #endif
  1462.   
  1463.   result = dlp_exec(sd, 0x22, 0x20, dlp_buf, 6, 0, 0);
  1464.   
  1465.   Expect(0);
  1466.   
  1467.   return result;
  1468. }
  1469.  
  1470.  
  1471. int dlp_ReadResourceByType(int sd, int fHandle, unsigned long type, int id, void* buffer, 
  1472.                           int* index, int* size)
  1473. {
  1474.   int result;
  1475.   
  1476.   set_byte(dlp_buf, fHandle);
  1477.   set_byte(dlp_buf+1, 0x00);
  1478.   set_long(dlp_buf+2, type);
  1479.   set_short(dlp_buf+6, id);
  1480.   set_short(dlp_buf+8, 0); /* Offset into record */
  1481.   set_short(dlp_buf+10, buffer ? DLP_BUF_SIZE : 0); /* length to return */
  1482.  
  1483.   Trace(ReadResourceByType);
  1484.  
  1485. #ifdef DLP_TRACE
  1486.   if (dlp_trace) {  
  1487.     fprintf(stderr, " Wrote: Handle: %d, Type: '%s', ID: %d\n",
  1488.       fHandle, printlong(type), id);
  1489.   }
  1490. #endif
  1491.  
  1492.   result = dlp_exec(sd, 0x23, 0x21, dlp_buf, 12, dlp_buf, DLP_BUF_SIZE);
  1493.   
  1494.   Expect(10);
  1495.  
  1496. #ifdef DLP_TRACE
  1497.   if (dlp_trace) {  
  1498.     fprintf(stderr, "  Read: Type: '%s', ID: %d, Index: %d, and %d bytes:\n",
  1499.       printlong(type), id, get_short(dlp_buf+6), result-10);
  1500.     dumpdata(dlp_buf+10, result-10);
  1501.   }
  1502. #endif
  1503.   
  1504.   if (index)
  1505.     *index = get_short(dlp_buf+6);
  1506.   if (size)
  1507.     *size = get_short(dlp_buf+8);
  1508.   if (buffer)
  1509.     memcpy(buffer, dlp_buf+10, result-10);
  1510.  
  1511.   return result-10;
  1512. }
  1513.  
  1514. int dlp_ReadResourceByIndex(int sd, int fHandle, int index, void* buffer,
  1515.                           unsigned long* type, int * id, int* size)
  1516. {
  1517.   int result;
  1518.   
  1519.   set_byte(dlp_buf, fHandle);
  1520.   set_byte(dlp_buf+1, 0x00);
  1521.   set_short(dlp_buf+2, index);
  1522.   set_short(dlp_buf+4, 0); /* Offset into record */
  1523.   set_short(dlp_buf+6, buffer ? DLP_BUF_SIZE : 0); /* length to return */
  1524.  
  1525.   Trace(ReadResourceByIndex);
  1526.  
  1527. #ifdef DLP_TRACE
  1528.   if (dlp_trace) {  
  1529.     fprintf(stderr, " Wrote: Handle: %d, Index: %d\n",
  1530.       fHandle, index);
  1531.   }
  1532. #endif
  1533.  
  1534.   result = dlp_exec(sd, 0x23, 0x20, dlp_buf, 8, dlp_buf, DLP_BUF_SIZE);
  1535.   
  1536.   Expect(10);
  1537.  
  1538. #ifdef DLP_TRACE
  1539.   if (dlp_trace) {  
  1540.     fprintf(stderr, "  Read: Type: '%s', ID: %d, Index: %d, and %d bytes:\n",
  1541.       printlong(get_long(dlp_buf)), get_short(dlp_buf+4), index, result-10);
  1542.     dumpdata(dlp_buf+10, result-10);
  1543.   }
  1544. #endif
  1545.  
  1546.   if (type) 
  1547.     *type = get_long(dlp_buf);
  1548.   if (id)
  1549.     *id = get_short(dlp_buf+4);
  1550.   if (size)
  1551.     *size = get_short(dlp_buf+8);
  1552.   if (buffer)
  1553.     memcpy(buffer, dlp_buf+10, result-10);
  1554.    
  1555.   return result-10;
  1556. }
  1557.  
  1558. int dlp_WriteResource(int sd, int dbhandle, unsigned long type, int id,
  1559.                  const void* data, int length)
  1560. {
  1561.   int result;
  1562.   
  1563.   set_byte(dlp_buf, dbhandle);
  1564.   set_byte(dlp_buf+1, 0);
  1565.   set_long(dlp_buf+2, type);
  1566.   set_short(dlp_buf+6, id);
  1567.   set_short(dlp_buf+8, length);
  1568.  
  1569.   if (length+10 > DLP_BUF_SIZE) {
  1570.     fprintf(stderr, "Data too large\n");
  1571.     return -131;
  1572.   }
  1573.  
  1574.   memcpy(dlp_buf+10, data, length);
  1575.   
  1576.   Trace(WriteResource);
  1577.  
  1578. #ifdef DLP_TRACE
  1579.   if (dlp_trace) {  
  1580.     fprintf(stderr, " Wrote: Type: '%s', ID: %d, and %d bytes:\n",
  1581.       printlong(type), id, length);
  1582.     dumpdata(data, length);
  1583.   }
  1584. #endif
  1585.  
  1586.   result = dlp_exec(sd, 0x24, 0x20, dlp_buf, 10+length, NULL, 0);
  1587.   
  1588.   Expect(0);
  1589.   
  1590.   return result;
  1591. }
  1592.  
  1593. int dlp_DeleteResource(int sd, int dbhandle, int all, unsigned long restype, int resID)
  1594. {
  1595.   int result;
  1596.   int flags = all ? 0x80 : 0;
  1597.  
  1598.   set_byte(dlp_buf, dbhandle);
  1599.   set_byte(dlp_buf+1, flags);
  1600.   set_long(dlp_buf+2, restype);
  1601.   set_short(dlp_buf+6, resID);
  1602.  
  1603.   Trace(DeleteResource);
  1604.  
  1605. #ifdef DLP_TRACE
  1606.   if (dlp_trace) {  
  1607.     fprintf(stderr, " Wrote: Type: '%s', ID: %d, All: %s\n",
  1608.       printlong(restype), resID, all ? "Yes" : "No");
  1609.   }
  1610. #endif
  1611.   
  1612.   result = dlp_exec(sd, 0x25, 0x20, dlp_buf, 8, NULL, 0);
  1613.   
  1614.   Expect(0);
  1615.   
  1616.   return result;
  1617. }
  1618.  
  1619. int dlp_ReadAppBlock(int sd, int fHandle, int offset,
  1620.                            void* dbuf, int dlen)
  1621. {
  1622.   int result;
  1623.   
  1624.   set_byte(dlp_buf, fHandle);
  1625.   set_byte(dlp_buf+1, 0x00);
  1626.   set_short(dlp_buf+2, offset);
  1627.   set_short(dlp_buf+4, dlen);
  1628.   
  1629.   Trace(ReadAppBlock);
  1630.  
  1631. #ifdef DLP_TRACE
  1632.   if (dlp_trace) {  
  1633.     fprintf(stderr, " Wrote: Handle: %d, Offset: %d, Max Length: %d\n",
  1634.       fHandle, offset, dlen);
  1635.   }
  1636. #endif
  1637.   
  1638.   result = dlp_exec(sd, 0x1b, 0x20, dlp_buf, 6, dlp_buf, DLP_BUF_SIZE);
  1639.   
  1640.   Expect(2);
  1641.   
  1642.   if (dbuf)
  1643.     memcpy(dbuf, dlp_buf+2, result-2);
  1644.   
  1645. #ifdef DLP_TRACE
  1646.   if (dlp_trace) {  
  1647.     fprintf(stderr, "  Read: %d bytes:\n",
  1648.       result-2);
  1649.     dumpdata(dlp_buf+2, result-2);
  1650.   }
  1651. #endif
  1652.   
  1653.   return result-2;
  1654. }
  1655.  
  1656. int dlp_WriteAppBlock(int sd, int fHandle, const /*@unique@*/ void* data, int length)
  1657. {
  1658.   int result;
  1659.   
  1660.   set_byte(dlp_buf, fHandle);
  1661.   set_byte(dlp_buf+1, 0x00);
  1662.   set_short(dlp_buf+2, length);
  1663.  
  1664.   if (length+4 > DLP_BUF_SIZE) {
  1665.     fprintf(stderr, "Data too large\n");
  1666.     return -131;
  1667.   }
  1668.   
  1669.   memcpy(dlp_buf+4, data, length);
  1670.  
  1671.   Trace(WriteAppBlock);
  1672.  
  1673. #ifdef DLP_TRACE
  1674.   if (dlp_trace) {  
  1675.     fprintf(stderr, " Wrote: Handle: %d, %d bytes:\n",
  1676.       fHandle, length);
  1677.     dumpdata(data, length);
  1678.   }
  1679. #endif
  1680.  
  1681.   result = dlp_exec(sd, 0x1c, 0x20, dlp_buf, length+4, NULL, 0);
  1682.   
  1683.   Expect(0);
  1684.   
  1685.   return result;
  1686. }
  1687.  
  1688. int dlp_ReadSortBlock(int sd, int fHandle, int offset,
  1689.                            void* dbuf, int dlen)
  1690. {
  1691.   int result;
  1692.   
  1693.   set_byte(dlp_buf, fHandle);
  1694.   set_byte(dlp_buf+1, 0x00);
  1695.   set_short(dlp_buf+2, offset);
  1696.   set_short(dlp_buf+4, dlen);
  1697.  
  1698.   Trace(ReadSortBlock);
  1699.  
  1700. #ifdef DLP_TRACE
  1701.   if (dlp_trace) {  
  1702.     fprintf(stderr, " Wrote: Handle: %d, Offset: %d, Max Length: %d\n",
  1703.       fHandle, offset, dlen);
  1704.   }
  1705. #endif
  1706.   
  1707.   result = dlp_exec(sd, 0x1d, 0x20, dlp_buf, 6, dlp_buf, DLP_BUF_SIZE);
  1708.  
  1709. #ifdef DLP_TRACE
  1710.   if (dlp_trace) {  
  1711.     fprintf(stderr, "  Read: %d bytes:\n",
  1712.       result-2);
  1713.     dumpdata(dlp_buf+2, result-2);
  1714.   }
  1715. #endif
  1716.   
  1717.   if (dbuf)
  1718.     memcpy(dbuf, dlp_buf+2, result-2);
  1719.   return result-2;
  1720. }
  1721.  
  1722. int dlp_WriteSortBlock(int sd, int fHandle, const /*@unique@*/ void* data, int length)
  1723. {
  1724.   int result;
  1725.   set_byte(dlp_buf, fHandle);
  1726.   set_byte(dlp_buf+1, 0x00);
  1727.   set_short(dlp_buf+2, length);
  1728.  
  1729.   if (length+4 > DLP_BUF_SIZE) {
  1730.     fprintf(stderr, "Data too large\n");
  1731.     return -131;
  1732.   }
  1733.   
  1734.   memcpy(dlp_buf+4, data, length);
  1735.  
  1736.   Trace(WriteSortBlock);
  1737.  
  1738. #ifdef DLP_TRACE
  1739.   if (dlp_trace) {  
  1740.     fprintf(stderr, " Wrote: Handle: %d, %d bytes:\n",
  1741.       fHandle, length);
  1742.     dumpdata(data, length);
  1743.   }
  1744. #endif
  1745.  
  1746.   result = dlp_exec(sd, 0x1e, 0x20, dlp_buf, length+4, NULL, 0);
  1747.  
  1748.   Expect(0);
  1749.   
  1750.   return result;
  1751. }
  1752.  
  1753. int dlp_CleanUpDatabase(int sd, int fHandle)
  1754. {
  1755.   int result;
  1756.   unsigned char handle = fHandle;
  1757.  
  1758.   Trace(CleanUpDatabase);
  1759.  
  1760. #ifdef DLP_TRACE
  1761.   if (dlp_trace) {  
  1762.     fprintf(stderr, " Wrote: Handle: %d\n", fHandle);
  1763.   }
  1764. #endif
  1765.  
  1766.   result = dlp_exec(sd, 0x26, 0x20, &handle, 1, NULL, 0);
  1767.   
  1768.   Expect(0);
  1769.   
  1770.   return result;
  1771. }
  1772.  
  1773. int dlp_ResetSyncFlags(int sd, int fHandle)
  1774. {
  1775.   int result;
  1776.   unsigned char handle = fHandle;
  1777.  
  1778.   Trace(ResetSyncFlags);
  1779.  
  1780. #ifdef DLP_TRACE
  1781.   if (dlp_trace) {  
  1782.     fprintf(stderr, " Wrote: Handle: %d\n", fHandle);
  1783.   }
  1784. #endif
  1785.   
  1786.   result = dlp_exec(sd, 0x27, 0x20, &handle, 1, NULL, 0);
  1787.   
  1788.   Expect(0);
  1789.   
  1790.   return result;
  1791. }
  1792.  
  1793. int dlp_ReadNextRecInCategory(int sd, int fHandle, int incategory, void* buffer,
  1794.                           recordid_t* id, int* index, int* size, int* attr)
  1795. {
  1796.   int result;
  1797. #ifdef DLP_TRACE
  1798.   int flags;
  1799. #endif
  1800.  
  1801.   if (pi_version(sd) < 0x0101) {
  1802.     /* Emulate for PalmOS 1.0 */
  1803.     int cat;
  1804.     int r;
  1805.     struct pi_socket * ps;
  1806.  
  1807.     Trace(ReadNextRecInCategoryV1);
  1808.  
  1809. #ifdef DLP_TRACE
  1810.     if (dlp_trace) {  
  1811.       fprintf(stderr, " Emulating with: Handle: %d, Category: %d\n", fHandle, incategory);
  1812.     }
  1813. #endif
  1814.  
  1815.     if ((ps = find_pi_socket(sd))==0)
  1816.       return -130;
  1817.     
  1818.     for(;;) {
  1819.       /* Fetch next modified record (in any category) */
  1820.       r = dlp_ReadRecordByIndex(sd, fHandle, ps->dlprecord, 0, 0, 0, 0, &cat);
  1821.       
  1822.       if (r<0)
  1823.         break;
  1824.       
  1825.       if (cat != incategory) {
  1826.         ps->dlprecord++;
  1827.         continue;
  1828.       }
  1829.  
  1830.       r = dlp_ReadRecordByIndex(sd, fHandle, ps->dlprecord, buffer, id, size, attr, &cat);
  1831.       
  1832.       if (r >= 0) {
  1833.         if (index)
  1834.           *index = ps->dlprecord;
  1835.         ps->dlprecord++;
  1836.       } else {
  1837.         /* If none found, reset modified pointer so that another search on a different
  1838.            (or the same!) category will work */
  1839.         ps->dlprecord = 0;
  1840.       }
  1841.       
  1842.       break;
  1843.     }
  1844.     
  1845.     return r;
  1846.   }
  1847.  
  1848.   Trace(ReadNextRecInCategoryV2);
  1849.  
  1850.   set_byte(dlp_buf, fHandle);
  1851.   set_byte(dlp_buf+1, incategory);
  1852.   
  1853. #ifdef DLP_TRACE
  1854.   if (dlp_trace) {  
  1855.     fprintf(stderr, " Wrote: Handle: %d, Category: %d\n", fHandle, incategory);
  1856.   }
  1857. #endif
  1858.   
  1859.   result = dlp_exec(sd, 0x32, 0x20, dlp_buf, 2, dlp_buf, DLP_BUF_SIZE);
  1860.   
  1861.   Expect(10);
  1862.  
  1863. #ifdef DLP_TRACE
  1864.   if (dlp_trace) {  
  1865.     flags = get_byte(dlp_buf+8);
  1866.     fprintf(stderr, "  Read: ID: 0x%8.8lX, Index: %d, Category: %d\n        Flags:",
  1867.       (unsigned long)get_long(dlp_buf), get_short(dlp_buf+4), (int)get_byte(dlp_buf+9));
  1868.     if (flags & dlpRecAttrDeleted)
  1869.       fprintf(stderr, " Deleted");
  1870.     if (flags & dlpRecAttrDirty)
  1871.       fprintf(stderr, " Dirty");
  1872.     if (flags & dlpRecAttrBusy)
  1873.       fprintf(stderr, " Busy");
  1874.     if (flags & dlpRecAttrSecret)
  1875.       fprintf(stderr, " Secret");
  1876.     if (flags & dlpRecAttrArchived)
  1877.       fprintf(stderr, " Archive");
  1878.     if (!flags)
  1879.       fprintf(stderr, " None");
  1880.     fprintf(stderr, " (0x%2.2X), and %d bytes:\n", flags, result-10);
  1881.     dumpdata(dlp_buf+10, result-10);
  1882.   }
  1883. #endif
  1884.  
  1885.   if (id)
  1886.     *id = get_long(dlp_buf);
  1887.   if (index)
  1888.     *index = get_short(dlp_buf+4);
  1889.   if (size)
  1890.     *size = get_short(dlp_buf+6);
  1891.   if (attr)
  1892.     *attr = get_byte(dlp_buf+8);
  1893.   if (buffer)    
  1894.     memcpy(buffer, dlp_buf+10, result-10);
  1895.     
  1896.   return result-10;
  1897. }
  1898.  
  1899.  
  1900. int dlp_ReadAppPreference(int sd, unsigned long creator, int id, int backup,
  1901.                           int maxsize, void* buffer, int * size, int * version)
  1902. {
  1903.   int result;
  1904.  
  1905.   if (pi_version(sd) < 0x0101) {
  1906.     /* Emulate on PalmOS 1.0 */
  1907.     int db;
  1908.     int r;
  1909.  
  1910.     Trace(ReadAppPreferenceV1);
  1911.  
  1912. #ifdef DLP_TRACE
  1913.     if (dlp_trace) {  
  1914.       fprintf(stderr, "  Emulating with: Creator: '%s', Id: %d, Size: %d, Backup: %d\n", 
  1915.                       printlong(creator), id, buffer ? maxsize : 0, backup ? 0x80 : 0);
  1916.     }
  1917. #endif
  1918.     
  1919.     r = dlp_OpenDB(sd, 0, dlpOpenRead, "System Preferences", &db);
  1920.     if (r<0)
  1921.       return r;
  1922.     
  1923.     r = dlp_ReadResourceByType(sd, db, creator, id, buffer, NULL, size);
  1924.     
  1925.     
  1926.     if (r<0) {
  1927.       dlp_CloseDB(sd, db);
  1928.       return r;
  1929.     }
  1930.  
  1931.     if (size)
  1932.       *size -= 2;
  1933.     
  1934.     if (version)
  1935.       *version = get_short(buffer);
  1936.     
  1937.     if (r>2) {
  1938.       r-=2;
  1939.       memmove(buffer, ((char*)buffer)+2, r);
  1940.     } else {
  1941.       r = 0;
  1942.     }
  1943.     
  1944.     dlp_CloseDB(sd,db);
  1945.  
  1946.     return r;
  1947.   }
  1948.  
  1949.   Trace(ReadAppPreferenceV2);
  1950.  
  1951.   set_long(dlp_buf, creator);
  1952.   set_short(dlp_buf+4, id);
  1953.   set_short(dlp_buf+6, buffer ? maxsize : 0);
  1954.   set_byte(dlp_buf+8, backup ? 0x80 : 0);
  1955.   set_byte(dlp_buf+9, 0); /* Reserved */
  1956.   
  1957. #ifdef DLP_TRACE
  1958.   if (dlp_trace) {  
  1959.     fprintf(stderr, " Wrote: Creator: '%s', Id: %d, Size: %d, Backup: %d\n", 
  1960.                 printlong(creator), id, buffer ? maxsize : 0, backup ? 0x80 : 0);
  1961.   }
  1962. #endif
  1963.   
  1964.   result = dlp_exec(sd, 0x34, 0x20, dlp_buf, 10, dlp_buf, DLP_BUF_SIZE);
  1965.   
  1966.   Expect(6);
  1967.  
  1968. #ifdef DLP_TRACE
  1969.   if (dlp_trace) {  
  1970.     fprintf(stderr, " Read: Version: %d, Total size: %d, Read %d bytes:\n", 
  1971.                    get_short(dlp_buf), get_short(dlp_buf+2), get_short(dlp_buf+4));
  1972.     dumpdata(dlp_buf+6, get_short(dlp_buf+4));
  1973.   }
  1974. #endif
  1975.  
  1976.   if (version)
  1977.     *version = get_short(dlp_buf);
  1978.   if (size && !buffer)
  1979.     *size = get_short(dlp_buf+2); /* Total size */
  1980.   if (size && buffer)
  1981.     *size = get_short(dlp_buf+4); /* Size returned */
  1982.   if (buffer)
  1983.     memcpy(buffer, dlp_buf+6, get_short(dlp_buf+4));
  1984.     
  1985.   return get_short(dlp_buf+4);
  1986. }
  1987.  
  1988. int dlp_WriteAppPreference(int sd, unsigned long creator, int id, int backup,
  1989.                           int version, void * buffer, int size)
  1990. {
  1991.   int result;
  1992.  
  1993.   if (pi_version(sd) < 0x0101) {
  1994.     /* Emulate on PalmOS 1.0 */
  1995.     int db;
  1996.     int r;
  1997.  
  1998.     Trace(WriteAppPreferenceV1);
  1999.  
  2000. #ifdef DLP_TRACE
  2001.   if (dlp_trace) {  
  2002.     fprintf(stderr, " Wrote: Creator: '%s', Id: %d, Version: %d, Backup: %d, and %d bytes:\n", 
  2003.                     printlong(creator), id, version, backup ? 0x80 : 0, size);
  2004.     dumpdata(buffer, size);
  2005.   }
  2006. #endif
  2007.     
  2008.     r = dlp_OpenDB(sd, 0, dlpOpenWrite, "System Preferences", &db);
  2009.     if (r<0)
  2010.       return r;
  2011.       
  2012.     if (buffer && size) {
  2013.       memcpy(dlp_buf + 2, buffer, size);
  2014.       set_short(dlp_buf, version);
  2015.       r = dlp_WriteResource(sd, db, creator, id, dlp_buf, size);
  2016.     } else
  2017.       r = dlp_WriteResource(sd, db, creator, id, NULL, 0);
  2018.  
  2019.     dlp_CloseDB(sd, db);
  2020.     
  2021.     return r;
  2022.   }
  2023.  
  2024.   Trace(WriteAppPreferenceV2);
  2025.  
  2026.   set_long(dlp_buf, creator);
  2027.   set_short(dlp_buf+4, id);
  2028.   set_short(dlp_buf+6, version);
  2029.   set_short(dlp_buf+8, size);
  2030.   set_byte(dlp_buf+10, backup ? 0x80 : 0);
  2031.   set_byte(dlp_buf+11, 0); /* Reserved */
  2032.   
  2033.   if (size+12 > DLP_BUF_SIZE) {
  2034.     fprintf(stderr, "Data too large\n");
  2035.     return -131;
  2036.   }
  2037.   
  2038.   memcpy(dlp_buf+12, buffer, size);
  2039.   
  2040. #ifdef DLP_TRACE
  2041.   if (dlp_trace) {  
  2042.     fprintf(stderr, " Wrote: Creator: '%s', Id: %d, Version: %d, Backup: %d, and %d bytes:\n", 
  2043.                     printlong(creator), id, version, backup ? 0x80 : 0, size);
  2044.     dumpdata(buffer, size);
  2045.   }
  2046. #endif
  2047.   
  2048.   result = dlp_exec(sd, 0x35, 0x20, dlp_buf, 12+size, NULL, 0);
  2049.   
  2050.   Expect(0);
  2051.  
  2052.   return result;
  2053. }
  2054.  
  2055. int dlp_ReadNextModifiedRecInCategory(int sd, int fHandle, int incategory, void* buffer,
  2056.                           recordid_t* id, int* index, int* size, int* attr)
  2057. {
  2058.   int result;
  2059. #ifdef DLP_TRACE
  2060.   int flags;
  2061. #endif
  2062.  
  2063.   if (pi_version(sd) < 0x0101) {
  2064.     /* Emulate for PalmOS 1.0 */
  2065.     int cat;
  2066.     int r;
  2067.  
  2068.     Trace(ReadNextModifiedRecInCategoryV1);
  2069.  
  2070. #ifdef DLP_TRACE
  2071.   if (dlp_trace) {  
  2072.     fprintf(stderr, " Emulating with: Handle: %d, Category: %d\n", fHandle, incategory);
  2073.   }
  2074. #endif
  2075.     
  2076.     do {
  2077.       /* Fetch next modified record (in any category) */
  2078.       r = dlp_ReadNextModifiedRec(sd, fHandle, buffer, id, index, size, attr, &cat);
  2079.     
  2080.       /* If none found, reset modified pointer so that another search on a different
  2081.          (or the same!) category will start from the beginning */
  2082.       if (r < 0)
  2083.         dlp_ResetDBIndex(sd, fHandle);
  2084.           
  2085.       /* Loop until we fail to get a record or a record is found in the proper category */
  2086.     } while ((r >= 0) && (cat != incategory));
  2087.     
  2088.     return r;
  2089.   }
  2090.  
  2091.   Trace(ReadNextModifiedRecInCategoryV2);
  2092.  
  2093.   set_byte(dlp_buf, fHandle);
  2094.   set_byte(dlp_buf+1, incategory);
  2095.   
  2096. #ifdef DLP_TRACE
  2097.   if (dlp_trace) {  
  2098.     fprintf(stderr, " Wrote: Handle: %d, Category: %d\n", fHandle, incategory);
  2099.   }
  2100. #endif
  2101.   
  2102.   result = dlp_exec(sd, 0x33, 0x20, dlp_buf, 2, dlp_buf, DLP_BUF_SIZE);
  2103.   
  2104.   Expect(10);
  2105.  
  2106. #ifdef DLP_TRACE
  2107.   if (dlp_trace) {  
  2108.     flags = get_byte(dlp_buf+8);
  2109.     fprintf(stderr, "  Read: ID: 0x%8.8lX, Index: %d, Category: %d\n        Flags:",
  2110.       (unsigned long)get_long(dlp_buf), get_short(dlp_buf+4), (int)get_byte(dlp_buf+9));
  2111.     if (flags & dlpRecAttrDeleted)
  2112.       fprintf(stderr, " Deleted");
  2113.     if (flags & dlpRecAttrDirty)
  2114.       fprintf(stderr, " Dirty");
  2115.     if (flags & dlpRecAttrBusy)
  2116.       fprintf(stderr, " Busy");
  2117.     if (flags & dlpRecAttrSecret)
  2118.       fprintf(stderr, " Secret");
  2119.     if (flags & dlpRecAttrArchived)
  2120.       fprintf(stderr, " Archive");
  2121.     if (!flags)
  2122.       fprintf(stderr, " None");
  2123.     fprintf(stderr, " (0x%2.2X), and %d bytes:\n", flags, result-10);
  2124.     dumpdata(dlp_buf+10, result-10);
  2125.   }
  2126. #endif
  2127.  
  2128.   if (id)
  2129.     *id = get_long(dlp_buf);
  2130.   if (index)
  2131.     *index = get_short(dlp_buf+4);
  2132.   if (size)
  2133.     *size = get_short(dlp_buf+6);
  2134.   if (attr)
  2135.     *attr = get_byte(dlp_buf+8);
  2136.   if (buffer)    
  2137.     memcpy(buffer, dlp_buf+10, result-10);
  2138.     
  2139.   return result-10;
  2140. }
  2141.  
  2142.  
  2143. int dlp_ReadNextModifiedRec(int sd, int fHandle, void* buffer,
  2144.                           recordid_t* id, int* index, int* size, int* attr, int* category)
  2145. {
  2146.   unsigned char handle = fHandle;
  2147.   int result;
  2148. #ifdef DLP_TRACE
  2149.   int flags;
  2150. #endif
  2151.  
  2152.   Trace(ReadNextModifiedRec);
  2153.  
  2154. #ifdef DLP_TRACE
  2155.   if (dlp_trace) {  
  2156.     fprintf(stderr, " Wrote: Handle: %d\n", fHandle);
  2157.   }
  2158. #endif
  2159.   
  2160.   result = dlp_exec(sd, 0x1f, 0x20, &handle, 1, dlp_buf, DLP_BUF_SIZE);
  2161.   
  2162.   Expect(10);
  2163.  
  2164. #ifdef DLP_TRACE
  2165.   if (dlp_trace) {  
  2166.     flags = get_byte(dlp_buf+8);
  2167.     fprintf(stderr, "  Read: ID: 0x%8.8lX, Index: %d, Category: %d\n        Flags:",
  2168.       (unsigned long)get_long(dlp_buf), get_short(dlp_buf+4), (int)get_byte(dlp_buf+9));
  2169.     if (flags & dlpRecAttrDeleted)
  2170.       fprintf(stderr, " Deleted");
  2171.     if (flags & dlpRecAttrDirty)
  2172.       fprintf(stderr, " Dirty");
  2173.     if (flags & dlpRecAttrBusy)
  2174.       fprintf(stderr, " Busy");
  2175.     if (flags & dlpRecAttrSecret)
  2176.       fprintf(stderr, " Secret");
  2177.     if (flags & dlpRecAttrArchived)
  2178.       fprintf(stderr, " Archive");
  2179.     if (!flags)
  2180.       fprintf(stderr, " None");
  2181.     fprintf(stderr, " (0x%2.2X), and %d bytes:\n", flags, result-10);
  2182.     dumpdata(dlp_buf+10, result-10);
  2183.   }
  2184. #endif
  2185.  
  2186.   if (id)
  2187.     *id = get_long(dlp_buf);
  2188.   if (index)
  2189.     *index = get_short(dlp_buf+4);
  2190.   if (size)
  2191.     *size = get_short(dlp_buf+6);
  2192.   if (attr)
  2193.     *attr = get_byte(dlp_buf+8);
  2194.   if (category)
  2195.     *category = get_byte(dlp_buf+9);
  2196.   if (buffer)    
  2197.     memcpy(buffer, dlp_buf+10, result-10);
  2198.     
  2199.   return result-10;
  2200. }
  2201.  
  2202. int dlp_ReadRecordById(int sd, int fHandle, recordid_t id, void* buffer, 
  2203.                           int* index, int* size, int* attr, int* category)
  2204. {
  2205.   int result;
  2206. #ifdef DLP_TRACE
  2207.   int flags;
  2208. #endif
  2209.   
  2210.   set_byte(dlp_buf, fHandle);
  2211.   set_byte(dlp_buf+1, 0x00);
  2212.   set_long(dlp_buf+2, id);
  2213.   set_short(dlp_buf+6, 0); /* Offset into record */
  2214.   set_short(dlp_buf+8, buffer ? DLP_BUF_SIZE : 0); /* length to return */
  2215.  
  2216.   Trace(ReadRecordById);
  2217.  
  2218. #ifdef DLP_TRACE
  2219.   if (dlp_trace) {  
  2220.     fprintf(stderr, " Wrote: Handle: %d, Record ID: 0x%8.8lX\n", fHandle, id);
  2221.   }
  2222. #endif
  2223.   
  2224.   result = dlp_exec(sd, 0x20, 0x20, dlp_buf, 10, dlp_buf, DLP_BUF_SIZE);
  2225.  
  2226.   Expect(10);
  2227.  
  2228. #ifdef DLP_TRACE
  2229.   if (dlp_trace) {  
  2230.     flags = get_byte(dlp_buf+8);
  2231.     fprintf(stderr, "  Read: ID: 0x%8.8lX, Index: %d, Category: %d\n        Flags:",
  2232.       (unsigned long)get_long(dlp_buf), get_short(dlp_buf+4), (int)get_byte(dlp_buf+9));
  2233.     if (flags & dlpRecAttrDeleted)
  2234.       fprintf(stderr, " Deleted");
  2235.     if (flags & dlpRecAttrDirty)
  2236.       fprintf(stderr, " Dirty");
  2237.     if (flags & dlpRecAttrBusy)
  2238.       fprintf(stderr, " Busy");
  2239.     if (flags & dlpRecAttrSecret)
  2240.       fprintf(stderr, " Secret");
  2241.     if (flags & dlpRecAttrArchived)
  2242.       fprintf(stderr, " Archive");
  2243.     if (!flags)
  2244.       fprintf(stderr, " None");
  2245.     fprintf(stderr, " (0x%2.2X), and %d bytes:\n", flags, result-10);
  2246.     dumpdata(dlp_buf+10, result-10);
  2247.   }
  2248. #endif
  2249.   
  2250.   /*id = get_long(dlp_buf);*/
  2251.   if (index)
  2252.     *index = get_short(dlp_buf+4);
  2253.   if (size)
  2254.     *size = get_short(dlp_buf+6);
  2255.   if (attr)
  2256.     *attr = get_byte(dlp_buf+8);
  2257.   if (category)
  2258.     *category = get_byte(dlp_buf+9);
  2259.   if (buffer)
  2260.     memcpy(buffer, dlp_buf+10, result-10);
  2261.  
  2262.   return result-10;
  2263. }
  2264.  
  2265. int dlp_ReadRecordByIndex(int sd, int fHandle, int index, void* buffer,
  2266.                           recordid_t* id, int* size, int* attr, int* category)
  2267. {
  2268.   int result;
  2269. #ifdef DLP_TRACE
  2270.   int flags;
  2271. #endif
  2272.   
  2273.   set_byte(dlp_buf, fHandle);
  2274.   set_byte(dlp_buf+1, 0x00);
  2275.   set_short(dlp_buf+2, index);
  2276.   set_short(dlp_buf+4, 0); /* Offset into record */
  2277.   set_short(dlp_buf+6, buffer ? DLP_BUF_SIZE : 0); /* length to return */
  2278.  
  2279.   Trace(ReadRecordByIndex);
  2280.  
  2281. #ifdef DLP_TRACE
  2282.   if (dlp_trace) {  
  2283.     fprintf(stderr, " Wrote: Handle: %d, Index: %d\n", fHandle, index);
  2284.   }
  2285. #endif  
  2286.  
  2287.   result = dlp_exec(sd, 0x20, 0x21, dlp_buf, 8, dlp_buf, DLP_BUF_SIZE);
  2288.   
  2289.   Expect(10);
  2290.   
  2291. #ifdef DLP_TRACE
  2292.   if (dlp_trace) {  
  2293.     flags = get_byte(dlp_buf+8);
  2294.     fprintf(stderr, "  Read: ID: 0x%8.8lX, Index: %d, Category: %d\n        Flags:",
  2295.       (unsigned long)get_long(dlp_buf), get_short(dlp_buf+4), (int)get_byte(dlp_buf+9));
  2296.     if (flags & dlpRecAttrDeleted)
  2297.       fprintf(stderr, " Deleted");
  2298.     if (flags & dlpRecAttrDirty)
  2299.       fprintf(stderr, " Dirty");
  2300.     if (flags & dlpRecAttrBusy)
  2301.       fprintf(stderr, " Busy");
  2302.     if (flags & dlpRecAttrSecret)
  2303.       fprintf(stderr, " Secret");
  2304.     if (flags & dlpRecAttrArchived)
  2305.       fprintf(stderr, " Archive");
  2306.     if (!flags)
  2307.       fprintf(stderr, " None");
  2308.     fprintf(stderr, " (0x%2.2X), and %d bytes:\n", flags, result-10);
  2309.     dumpdata(dlp_buf+10, result-10);
  2310.   }
  2311. #endif
  2312.  
  2313.   if (id)
  2314.     *id = get_long(dlp_buf);
  2315.   /*get_short(dlp_buf+4) == index*/
  2316.   if (size)
  2317.     *size = get_short(dlp_buf+6);
  2318.   if (attr)
  2319.     *attr = get_byte(dlp_buf+8);
  2320.   if (category)
  2321.     *category = get_byte(dlp_buf+9);
  2322.   if (buffer)
  2323.     memcpy(buffer, dlp_buf+10, result-10);
  2324.  
  2325.   return result-10;
  2326. }
  2327.